#ifndef _HANDLER_H_
#define _HANDLER_H_
#include "Defs.h"
#include "ActionOpt.h"
#include "Settings.h"


/**
* @brief:
* Cmd handler for receiving and executing
*
* Protocol: 0xFB 0xBF len(1B) cmd(1B) params(nB) checksum(1B) 0xED
* len: total size(including 0xFB...0xED)
* Checksum: LOW_B(len + cmd + params)
*
* Only support ASCII-string
* The return value of sub-function only indicates processed or not.
*/
class CHandler
{
public:
	CHandler();
	~CHandler();

	static uint8_t Checksum(int size, const uint8_t *data);

	AeRet_t HandleCmd(int size, const uint8_t *data, int &expect, uint8_t *out);

protected:
	// Version
	AeRet_t getVersion(int size, const uint8_t *data, int &expect, uint8_t *out);

	// Storage
	AeRet_t getStorage(int size, const uint8_t *data, int &expect, uint8_t *out);

	// Action
	AeRet_t getActions(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t playAction(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t stopAction(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t ctrlAction(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t deleteAction(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t uploadAction(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t uploadActSending(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t uploadActFinished(int size, const uint8_t *data, int &expect, uint8_t *out);

	// Voice
	AeRet_t offOnVoice(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t setVolume(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t playMusic(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t stopMusic(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t ctrlMusic(int size, const uint8_t *data, int &expect, uint8_t *out);

	// Servo
	AeRet_t setServoLed(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t setServosLed(int size, const uint8_t *data, int &expect, uint8_t *out);

	AeRet_t setServoAngle(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t setServosAngle(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t getServoAngle(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t getServosAngle(int size, const uint8_t *data, int &expect, uint8_t *out);

	AeRet_t setServoOffset(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t setServosOffset(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t getServoOffset(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t getServosOffset(int size, const uint8_t *data, int &expect, uint8_t *out);

	AeRet_t lockServos(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t unlockServos(int size, const uint8_t *data, int &expect, uint8_t *out);

	AeRet_t getServoFirmware(int size, const uint8_t *data, int &expect, uint8_t *out);
	AeRet_t getServosFirmware(int size, const uint8_t *data, int &expect, uint8_t *out);

  // Teaching
  AeRet_t startTeaching(int size, const uint8_t *data, int &expect, uint8_t *out);
  AeRet_t stopTeaching(int size, const uint8_t *data, int &expect, uint8_t *out);

protected:
	void putU32(int &offset, uint8_t *data, uint32_t val);
};


#endif

